﻿using System;
using System.Text.RegularExpressions;
using System.Threading;
using com.magickms._db;
using com.magickms.enums;
using com.magickms.model;

namespace com.magickms.robot
{
    public class KmsRobot : IRobot
    {
        #region 全局变量
        public ETarget Target { get; set; }
        public EMethod Method { get; set; }

        private bool _running;
        private bool _halted;

        private int _lastIndex;

        private Thread _thread;

        private TrayPtn _trayPtn;
        private Random _random;
        private ITarget _target;
        private MSession _session;
        #endregion

        #region 构造函数
        public KmsRobot(TrayPtn trayPtn)
        {
            _trayPtn = trayPtn;
        }
        #endregion

        #region 对外接口
        /// <summary>
        /// 
        /// </summary>
        /// <param name="solution"></param>
        /// <param name="note"></param>
        /// <returns></returns>
        public bool Deal(MSession session)
        {
            if (_trayPtn == null)
            {
                return false;
            }

            MSolution sln = _trayPtn.Solution;

            // 方案为空判断
            if (sln == null)
            {
                _target.ShowWarning("请选择会话方案！");
                return false;
            }

            // 标签资源：不指定标签时，使用所有标签
            if (sln.Category == null)
            {
                _target.ShowWarning("请选择标签资源！");
                return false;
            }

            // 语言资源
            sln.Sentence = DBA1000.ListSentence(sln.Category);
            if (sln.Sentence.Count < 1)
            {
                _target.ShowWarning("大哥，$robot_name$没的可说，给点提示吧！");
                return false;
            }

            // 随机数生成器
            if (_random == null)
            {
                _random = new Random();
            }

            _session = session;
            _session.Question.Clear();
            _session.Response.Clear();

            if (_thread == null || !_thread.IsAlive)
            {
                _thread = new Thread(new ThreadStart(DoDeal));
                _thread.SetApartmentState(System.Threading.ApartmentState.STA);
                _thread.Start();
            }
            return true;
        }

        public void Work()
        {
            if (_running)
            {
                return;
            }

            _running = true;
            _halted = false;
        }

        public void Halt()
        {
            if (!_running)
            {
                return;
            }
            _halted = true;
        }

        public void Next()
        {
            if (!_running)
            {
                return;
            }

            MSolution sln = _trayPtn.Solution;
            EMethod method = Method == EMethod.None ? sln.Method : Method;
            if (method == EMethod.Active)
            {
                Active(sln);
            }
            else
            {
                _halted = false;
            }
        }

        public void Stop()
        {
            if (!_running)
            {
                return;
            }
            _running = false;
            _halted = false;
        }

        public void AppendTarget(ITarget target)
        {
            _target = target;
        }

        public void RemoveTarget(ITarget target)
        {
            _target = null;
        }

        public bool Running
        {
            get
            {
                return _running;
            }
        }
        #endregion

        #region 公共方法

        /// <summary>
        /// 显示逐步提示
        /// </summary>
        public bool AlertByStep { get; set; }

        /// <summary>
        /// 是否随机选取发送
        /// </summary>
        public bool RandomSend { get; set; }

        /// <summary>
        /// 是否允许重复发送
        /// </summary>
        public bool RepeatSend { get; set; }

        /// <summary>
        /// 执行等待
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        public bool ThreadWait(string param)
        {
            if (string.IsNullOrEmpty(param))
            {
                if (AlertByStep)
                {
                    _target.ShowWarning("您输入了空等待时间！");
                }
                return false;
            }

            int time = 0;
            if (Regex.IsMatch(param, "^\\{\\d+,\\d+\\}$"))
            {
                string[] arr = param.Substring(1, param.Length - 2).Split(',');
                int min = int.Parse(arr[0]);
                int max = int.Parse(arr[1]);
                time = _random.Next(max - min) + min;
            }
            else if (Regex.IsMatch(param, "^\\d+$"))
            {
                time = int.Parse(param);
            }

            if (time > 0)
            {
                Thread.Sleep(time);
            }
            return true;
        }
        #endregion

        #region 私有方法

        private void DoDeal()
        {
            MSolution sln = _trayPtn.Solution;

            // 前置操作
            if (!_target.Prepare(sln.PreFunction))
            {
                _trayPtn.SessionEnd();
                return;
            }

            EMethod method = Method == EMethod.None ? sln.Method : Method;
            // 会话
            switch (method)
            {
                case EMethod.Answer:
                    Answer(sln);
                    break;
                //case EMethod.Active:
                //    Active(sln);
                //    break;
                case EMethod.Attack:
                    Attack(sln);
                    break;
                default:
                    break;
            }

            // 后置操作
            if (!_target.Confirm(sln.SufFunction))
            {
                _trayPtn.SessionEnd();
                return;
            }
        }

        private void DoHalt()
        {
            while (_halted)
            {
                Thread.Sleep(100);
            }
        }

        private void Answer(MSolution sln)
        {
            DBA1000.FindQuestion(_session.Question, _session.RawInput, _session.Style, _session.Language, _session.Category);
            _session.QIndex = 0;
            if (_session.Question.Count < 1)
            {
                _target.SendMessage(sln, _session.RawInput);
                return;
            }
            DBA1000.FindResponse(_session.Response, _session.Question[0].P3100103, _session.Style, _session.Language, _session.Category);
            _session.RIndex = 0;
            if (_session.Response.Count < 1)
            {
                _target.SendMessage(sln, _session.RawInput);
                return;
            }

            _target.SendMessage(sln, _session.Response[_session.RIndex].P3100105);
        }

        private void Active(MSolution sln)
        {
            int cnt = sln.Sentence.Count;
            if (!RandomSend)
            {
                if (_lastIndex < cnt)
                {
                    _target.SendMessage(sln, sln.Sentence[_lastIndex].P3100105);

                    _lastIndex += 1;
                }
                else
                {
                    _running = false;
                    _halted = false;
                    _trayPtn.SessionEnd();
                }
            }
            else
            {
                if (cnt > 0)
                {
                    _lastIndex = _random.Next(cnt);
                    _target.SendMessage(sln, sln.Sentence[_lastIndex].P3100105);
                    if (!RepeatSend)
                    {
                        sln.Sentence.RemoveAt(_lastIndex);
                    }
                }
                else
                {
                    _running = false;
                    _halted = false;
                    _trayPtn.SessionEnd();
                }
            }
        }

        private void Attack(MSolution sln)
        {
            int cnt = sln.Sentence.Count;
            int idx = 0;
            if (!RandomSend)
            {
                while (_running && idx < cnt)
                {
                    DoHalt();

                    _target.SendMessage(sln, sln.Sentence[idx].P3100105);

                    idx += 1;
                    if (sln.Intval > 0)
                    {
                        Thread.Sleep(sln.Intval * 1000);
                    }
                }
            }
            else
            {
                while (_running && cnt > 0)
                {
                    DoHalt();

                    idx = _random.Next(cnt);
                    _target.SendMessage(sln, sln.Sentence[idx].P3100105);
                    if (!RepeatSend)
                    {
                        sln.Sentence.RemoveAt(idx);
                    }

                    cnt -= 1;
                    if (sln.Intval > 0)
                    {
                        Thread.Sleep(sln.Intval * 1000);
                    }
                }
            }

            _running = false;
            _halted = false;
            _trayPtn.SessionEnd();
        }
        #endregion
    }
}
